]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSMacOS9/Mac OS Test Responder.c
mDNSResponder-66.3.tar.gz
[apple/mdnsresponder.git] / mDNSMacOS9 / Mac OS Test Responder.c
1 /*
2 * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24
25 Change History (most recent first):
26
27 $Log: Mac\040OS\040Test\040Responder.c,v $
28 Revision 1.21 2004/03/12 21:30:25 cheshire
29 Build a System-Context Shared Library from mDNSCore, for the benefit of developers
30 like Muse Research who want to be able to use mDNS/DNS-SD from GPL-licensed code.
31
32 Revision 1.20 2004/02/09 23:23:32 cheshire
33 Advertise "IL 2\4th Floor.apple.com." as another test "browse domain"
34
35 Revision 1.19 2004/01/24 23:55:15 cheshire
36 Change to use mDNSOpaque16fromIntVal/mDNSVal16 instead of shifting and masking
37
38 Revision 1.18 2003/11/14 21:27:08 cheshire
39 <rdar://problem/3484766>: Security: Crashing bug in mDNSResponder
40 Fix code that should use buffer size MAX_ESCAPED_DOMAIN_NAME (1005) instead of 256-byte buffers.
41
42 Revision 1.17 2003/08/14 02:19:54 cheshire
43 <rdar://problem/3375491> Split generic ResourceRecord type into two separate types: AuthRecord and CacheRecord
44
45 Revision 1.16 2003/08/12 19:56:24 cheshire
46 Update to APSL 2.0
47
48 */
49
50 #include <stdio.h> // For printf()
51 #include <string.h> // For strlen() etc.
52
53 #include <Events.h> // For WaitNextEvent()
54 #include <SIOUX.h> // For SIOUXHandleOneEvent()
55
56 #include "mDNSClientAPI.h" // Defines the interface to the client layer above
57
58 #include "mDNSMacOS9.h" // Defines the specific types needed to run mDNS on this platform
59
60 // These don't have to be globals, but their memory does need to remain valid for as
61 // long as the search is going on. They are declared as globals here for simplicity.
62 static mDNS m;
63 static mDNS_PlatformSupport p;
64 static ServiceRecordSet p1, p2, afp, http, njp;
65 static AuthRecord browsedomain1, browsedomain2;
66
67 // This sample code just calls mDNS_RenameAndReregisterService to automatically pick a new
68 // unique name for the service. For a device such as a printer, this may be appropriate.
69 // For a device with a user interface, and a screen, and a keyboard, the appropriate
70 // response may be to prompt the user and ask them to choose a new name for the service.
71 mDNSlocal void Callback(mDNS *const m, ServiceRecordSet *const sr, mStatus result)
72 {
73 switch (result)
74 {
75 case mStatus_NoError: debugf("Callback: %##s Name Registered", sr->RR_SRV.resrec.name.c); break;
76 case mStatus_NameConflict: debugf("Callback: %##s Name Conflict", sr->RR_SRV.resrec.name.c); break;
77 case mStatus_MemFree: debugf("Callback: %##s Memory Free", sr->RR_SRV.resrec.name.c); break;
78 default: debugf("Callback: %##s Unknown Result %d", sr->RR_SRV.resrec.name.c, result); break;
79 }
80
81 if (result == mStatus_NameConflict) mDNS_RenameAndReregisterService(m, sr, mDNSNULL);
82 }
83
84 // RegisterService() is a simple wrapper function which takes C string
85 // parameters, converts them to domainname parameters, and calls mDNS_RegisterService()
86 mDNSlocal void RegisterService(mDNS *m, ServiceRecordSet *recordset,
87 UInt16 PortAsNumber, const char txtinfo[],
88 const domainlabel *const n, const char type[], const char domain[])
89 {
90 domainname t;
91 domainname d;
92 char buffer[MAX_ESCAPED_DOMAIN_NAME];
93 UInt8 txtbuffer[512];
94
95 MakeDomainNameFromDNSNameString(&t, type);
96 MakeDomainNameFromDNSNameString(&d, domain);
97
98 if (txtinfo)
99 {
100 strncpy((char*)txtbuffer+1, txtinfo, sizeof(txtbuffer)-1);
101 txtbuffer[0] = (UInt8)strlen(txtinfo);
102 }
103 else
104 txtbuffer[0] = 0;
105
106 mDNS_RegisterService(m, recordset,
107 n, &t, &d, // Name, type, domain
108 mDNSNULL, mDNSOpaque16fromIntVal(PortAsNumber),
109 txtbuffer, (mDNSu16)(1+txtbuffer[0]), // TXT data, length
110 mDNSNULL, 0, // Subtypes (none)
111 mDNSInterface_Any, // Interface ID
112 Callback, mDNSNULL); // Callback and context
113
114 ConvertDomainNameToCString(&recordset->RR_SRV.resrec.name, buffer);
115 printf("Made Service Records for %s\n", buffer);
116 }
117
118 // RegisterFakeServiceForTesting() simulates the effect of services being registered on
119 // dynamically-allocated port numbers. No real service exists on that port -- this is just for testing.
120 mDNSlocal void RegisterFakeServiceForTesting(mDNS *m, ServiceRecordSet *recordset, const char txtinfo[],
121 const char name[], const char type[], const char domain[])
122 {
123 static UInt16 NextPort = 0xF000;
124 domainlabel n;
125 MakeDomainLabelFromLiteralString(&n, name);
126 RegisterService(m, recordset, NextPort++, txtinfo, &n, type, domain);
127 }
128
129 // CreateProxyRegistrationForRealService() checks to see if the given port is currently
130 // in use, and if so, advertises the specified service as present on that port.
131 // This is useful for advertising existing real services (Personal Web Sharing, Personal
132 // File Sharing, etc.) that currently don't register with mDNS Service Discovery themselves.
133 mDNSlocal OSStatus CreateProxyRegistrationForRealService(mDNS *m, UInt16 PortAsNumber, const char txtinfo[],
134 const char *servicetype, ServiceRecordSet *recordset)
135 {
136 InetAddress ia;
137 TBind bindReq;
138 OSStatus err;
139 TEndpointInfo endpointinfo;
140 EndpointRef ep = OTOpenEndpoint(OTCreateConfiguration(kTCPName), 0, &endpointinfo, &err);
141 if (!ep || err) { printf("OTOpenEndpoint (CreateProxyRegistrationForRealService) failed %d", err); return(err); }
142
143 ia.fAddressType = AF_INET;
144 ia.fPort = mDNSOpaque16fromIntVal(PortAsNumber).NotAnInteger;
145 ia.fHost = 0;
146 bindReq.addr.maxlen = sizeof(ia);
147 bindReq.addr.len = sizeof(ia);
148 bindReq.addr.buf = (UInt8*)&ia;
149 bindReq.qlen = 0;
150 err = OTBind(ep, &bindReq, NULL);
151
152 if (err == kOTBadAddressErr)
153 RegisterService(m, recordset, PortAsNumber, txtinfo, &m->nicelabel, servicetype, "local.");
154 else if (err)
155 debugf("OTBind failed %d", err);
156
157 OTCloseProvider(ep);
158 return(noErr);
159 }
160
161 // Done once on startup, and then again every time our address changes
162 mDNSlocal OSStatus mDNSResponderTestSetup(mDNS *m)
163 {
164 char buffer[MAX_ESCAPED_DOMAIN_NAME];
165 mDNSv4Addr ip = m->HostInterfaces->ip.ip.v4;
166
167 ConvertDomainNameToCString(&m->hostname, buffer);
168 printf("Name %s\n", buffer);
169 printf("IP %d.%d.%d.%d\n", ip.b[0], ip.b[1], ip.b[2], ip.b[3]);
170
171 printf("\n");
172 printf("Registering Service Records\n");
173 // Create example printer discovery records
174 //static ServiceRecordSet p1, p2;
175
176 #define SRSET 0
177 #if SRSET==0
178 RegisterFakeServiceForTesting(m, &p1, "path=/index.html", "Web Server One", "_http._tcp.", "local.");
179 RegisterFakeServiceForTesting(m, &p2, "path=/path.html", "Web Server Two", "_http._tcp.", "local.");
180 #elif SRSET==1
181 RegisterFakeServiceForTesting(m, &p1, "rn=lpq1", "Epson Stylus 900N", "_printer._tcp.", "local.");
182 RegisterFakeServiceForTesting(m, &p2, "rn=lpq2", "HP LaserJet", "_printer._tcp.", "local.");
183 #else
184 RegisterFakeServiceForTesting(m, &p1, "rn=lpq3", "My Printer", "_printer._tcp.", "local.");
185 RegisterFakeServiceForTesting(m, &p2, "lrn=pq4", "My Other Printer", "_printer._tcp.", "local.");
186 #endif
187
188 // If AFP Server is running, register a record for it
189 CreateProxyRegistrationForRealService(m, 548, "", "_afpovertcp._tcp.", &afp);
190
191 // If Web Server is running, register a record for it
192 CreateProxyRegistrationForRealService(m, 80, "", "_http._tcp.", &http);
193
194 // And pretend we always have an NJP server running on port 80 too
195 //RegisterService(m, &njp, 80, "NJP/", &m->nicelabel, "_njp._tcp.", "local.");
196
197 // Advertise that apple.com. is available for browsing
198 mDNS_AdvertiseDomains(m, &browsedomain1, mDNS_DomainTypeBrowse, mDNSInterface_Any, "apple.com.");
199 mDNS_AdvertiseDomains(m, &browsedomain2, mDNS_DomainTypeBrowse, mDNSInterface_Any, "IL 2\\4th Floor.apple.com.");
200
201 return(kOTNoError);
202 }
203
204 // YieldSomeTime() just cooperatively yields some time to other processes running on classic Mac OS
205 mDNSlocal Boolean YieldSomeTime(UInt32 milliseconds)
206 {
207 extern Boolean SIOUXQuitting;
208 EventRecord e;
209 WaitNextEvent(everyEvent, &e, milliseconds / 17, NULL);
210 SIOUXHandleOneEvent(&e);
211 return(SIOUXQuitting);
212 }
213
214 int main()
215 {
216 mStatus err;
217 Boolean DoneSetup = false;
218
219 SIOUXSettings.asktosaveonclose = false;
220 SIOUXSettings.userwindowtitle = "\pMulticast DNS Responder";
221
222 printf("Multicast DNS Responder\n\n");
223 printf("This software reports errors using MacsBug breaks,\n");
224 printf("so if you don't have MacsBug installed your Mac may crash.\n\n");
225 printf("******************************************************************************\n");
226
227 err = InitOpenTransport();
228 if (err) { debugf("InitOpenTransport failed %d", err); return(err); }
229
230 err = mDNS_Init(&m, &p, mDNS_Init_NoCache, mDNS_Init_ZeroCacheSize,
231 mDNS_Init_AdvertiseLocalAddresses, mDNS_Init_NoInitCallback, mDNS_Init_NoInitCallbackContext);
232 if (err) return(err);
233
234 while (!YieldSomeTime(35))
235 {
236 #if MDNS_ONLYSYSTEMTASK
237 // For debugging, use "#define MDNS_ONLYSYSTEMTASK 1" and call mDNSPlatformIdle() periodically.
238 // For shipping code, don't define MDNS_ONLYSYSTEMTASK, and you don't need to call mDNSPlatformIdle()
239 extern void mDNSPlatformIdle(mDNS *const m);
240 mDNSPlatformIdle(&m); // Only needed for debugging version
241 #endif
242 if (m.mDNSPlatformStatus == mStatus_NoError && !DoneSetup)
243 {
244 DoneSetup = true;
245 printf("\nListening for mDNS queries...\n");
246 mDNSResponderTestSetup(&m);
247 }
248 }
249
250 if (p1.RR_SRV.resrec.RecordType ) mDNS_DeregisterService(&m, &p1);
251 if (p2.RR_SRV.resrec.RecordType ) mDNS_DeregisterService(&m, &p2);
252 if (afp.RR_SRV.resrec.RecordType ) mDNS_DeregisterService(&m, &afp);
253 if (http.RR_SRV.resrec.RecordType) mDNS_DeregisterService(&m, &http);
254 if (njp.RR_SRV.resrec.RecordType ) mDNS_DeregisterService(&m, &njp);
255
256 mDNS_Close(&m);
257
258 return(0);
259 }